package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.Employee;
import com.sky.entity.SetmealDish;
import com.sky.exception.AccountNameDuplicateException;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.exception.NameDuplicateException;
import com.sky.mapper.DishMapper;
import com.sky.result.PageBean;
import com.sky.result.Result;
import com.sky.service.DishFlavorService;
import com.sky.service.DishService;
import com.sky.service.SetmealDishService;
import com.sky.utils.ThreadLocalUtil;
import com.sky.vo.DishVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 菜品业务接口实现类
 *
 * @Author Vsunks.v
 * @Date 2023/5/2 16:19
 * @Blog blog.sunxiaowei.net
 * @Description:
 */
@Service
public class DishServiceImpl implements DishService {


    @Autowired
    DishMapper dishMapper;

    // 跨模块注入的时候，要注入目标模块的serviceBean，而非MapperBean
    @Autowired
    DishFlavorService dishFlavorService;


    @Autowired
    SetmealDishService setmealDishService;


    @Transactional
    /**
     * 新增菜品，包含口味信息
     *
     * @param dishDTO 包含口味信息的菜品
     * @return 是否成功
     */
    @Override
    public Result saveWithFlavors(DishDTO dishDTO) {
        // 创建Dish对象，并为成员赋值数据
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);

        // 检查菜品名称是否重复
        String name = dishDTO.getName();
        dish.setName(name);

        if (isNameDuplicate(dish)) {
            throw new NameDuplicateException(name + "重复，请修改后重试");
        }


        // 设置必要数据
        dish.setStatus(1);

        // Long empId = ThreadLocalUtil.getCurrentId();
        // dish.setCreateUser(empId);
        // dish.setUpdateUser(empId);
        // LocalDateTime now = LocalDateTime.now();
        // dish.setCreateTime(now);
        // dish.setUpdateTime(now);

        // 保存菜品基本信息
        int count = dishMapper.insert(dish);


        // 保存菜品成功后，再保存口味
        if (count > 0) {
            // 获取口味信息
            List<DishFlavor> flavors = dishDTO.getFlavors();

            if (flavors != null && flavors.size() > 0) {
                // 获取当前菜品id
                Long dishId = dish.getId();

                // 设置菜品id进菜品口味
                flavors.forEach(flavor -> flavor.setDishId(dishId));

                // 保存口味信息
                dishFlavorService.savBatch(flavors);
            }

            // 组织数据，并返回
            return Result.success(MessageConstant.DISH_SAVE_SUCCESS);
        }
        return Result.error(MessageConstant.DISH_SAVE_FAILED);
    }

    /**
     * 分页查询菜品（含菜品分类名称）
     *
     * @param dishPageQueryDTO 分页条件、查询条件
     * @return 符合要求的菜品（含菜品分类名称）
     */
    @Override
    public Result<PageBean> pageWithCategoryName(DishPageQueryDTO dishPageQueryDTO) {

        // 2. 获取分页参数，使用分页助手设置分页数据（要放在查询语句前面）
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());

        // 1. 封装查询条件，并根据条件查询所有
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishPageQueryDTO, dish);
        // List<DishVO> dishVOs = dishMapper.selectByCondition(dish);
        Page<DishVO> dishVOs = (Page<DishVO>) dishMapper.selectByCondition(dish);

        // 3. 根据查询结果，封装PageBean
        PageBean pageBean = new PageBean(dishVOs.getTotal(), dishVOs.getResult());

        // 4. 组织数据并返回
        return Result.success(pageBean);
    }

    /**
     * 根据id批量删除菜品
     *
     * @param ids id们
     * @return 删除的结果
     */
    @Override
    @Transactional
    public Result deleteByIds(List<Long> ids) {
        // 1. 删除前判断：任一个菜品都不能启用
        // select * from dish where id = 1
        // select * from dish where id in(1,2,3)
        // 1.1 根据ids查出多个菜品
        List<Dish> dishes = dishMapper.selectByIds(ids);

        for (Dish dish : dishes) {
            // 1.2 如果某个菜品是启用状态，则不允许删除
            if (StatusConstant.ENABLE.equals(dish.getStatus())) {
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }

        // 2. 删除前判断：被删菜品是否属于某个套餐
        // 2.1 根据菜品ids查询所属套餐
        List<SetmealDish> setmealDishes = setmealDishService.findByDishIds(ids);

        // 2.2 如果套餐集合长度>0，则不能删除
        if (setmealDishes != null && setmealDishes.size() > 0) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }

        // 3. 删除菜品及菜品口味
        // 3.1 删除口味（不需要考虑有没有对应的口味，没有也不会报错）
        dishFlavorService.deleteByDishIds(ids);

        // 3.2 删除菜品
        int count = dishMapper.deleteByIds(ids);

        // 4. 组织数据并返回
        return Result.success(MessageConstant.DISH_DELETE_SUCCESS);
    }

    /**
     * 根据id查询菜品（含口味）
     *
     * @param id 主键id
     * @return 菜品
     */
    @Override
    public Result<DishVO> findByIdWithFlavors(Long id) {
        // 查菜品基本数据
        List<Dish> dishes = dishMapper.selectByIds(Arrays.asList(id));

        // 根据菜品id查询器口味数据
        List<DishFlavor> dishFlavors = dishFlavorService.findByDishId(id);

        // 封装到VO对象
        DishVO dishVO = new DishVO();
        if (dishes.size() > 0) {
            Dish dish = dishes.get(0);
            BeanUtils.copyProperties(dish, dishVO);
            dishVO.setFlavors(dishFlavors);
            return Result.success(dishVO);
        }

        // 组织数据并返回
        return Result.error(MessageConstant.DISH_SELECT_FAILED);
    }

    /**
     * 根据id，修改菜品（含口味）
     *
     * @param dishDTO 菜品（含口味）
     * @return 修改的结果
     */
    @Override
    @Transactional
    public Result updateById(DishDTO dishDTO) {
        // 1. 直接保存菜品的基本信息
        // 1.1 创建Dish对象
        Dish dish = new Dish();

        // 1.2 复制基本信息
        BeanUtils.copyProperties(dishDTO, dish);


        // 0. 检查名称是否重复
        // 该判断可以保证 1. 新增和修改非状态字段时，查重； 2. 修改状态（非名称字段）字段时不查重
        // if (!(employee.getId() != null && employee.getStatus() != null)) {
        if (dish.getId() == null || dish.getStatus() == null) {
            if (isNameDuplicate(dish)) {
                throw new AccountNameDuplicateException(dish.getName() + "重复，请修改后重试");
            }
        }

        // 1.3 设置通用字段值
        // dish.setUpdateUser(ThreadLocalUtil.getCurrentId());
        // dish.setUpdateTime(LocalDateTime.now());

        // 1.4 保存
        int count = dishMapper.updateById(dish);

        // 2. 保存新的口味信息
        if (count > 0) {
            // 2.1 删除数据库中该菜品已有的口味信息
            Long dishId = dish.getId();
            dishFlavorService.deleteByDishIds(Arrays.asList(dishId));

            // 2.2 获取新的口味并添加
            List<DishFlavor> flavors = dishDTO.getFlavors();
            flavors.forEach(flavor -> flavor.setDishId(dishId));
            dishFlavorService.savBatch(flavors);

            // 3. 组织数据并返回
            return Result.success(MessageConstant.DISH_UPDATE_SUCCESS);
        }
        return Result.error(MessageConstant.DISH_UPDATE_FAILED);
    }

    /**
     * 根据套餐id，查询当前套餐中所有的菜品
     *
     * @param setmealId
     * @return
     */
    @Override
    public List<Dish> findBySetmealId(Long setmealId) {

        return dishMapper.selectBySetmealId(setmealId);
    }

    /**
     * 查询指定分类下的所有菜品（隐含条件：在售菜品）
     *
     * @param categoryId 分类id
     * @return
     */
    @Override
    public Result<List<Dish>> listByCategoryId(Long categoryId) {
        // 调用mapper查询
        List<Dish> dishes = dishMapper.selectByCategoryId(categoryId);

        // 组织数据并返回
        return Result.success(dishes);
    }

    /**
     * 按条件查询菜品（已知条件：分类id、菜品名称）
     *
     * @param dish 查询条件封装的对象
     * @return 符合要求的菜品集合
     */
    @Override
    public Result<List<DishVO>> listByCondition(Dish dish) {

        // 查询菜品基本信息（分类名称）
        List<DishVO> dishVOs = dishMapper.selectByCondition(dish);

        // 遍历菜品，获取id后，根据id查询口味，并封装
        dishVOs.forEach(dishVO -> {
            List<DishFlavor> flavors = dishFlavorService.findByDishId(dishVO.getId());
            dishVO.setFlavors(flavors);
        });

        // 组织数据并响应
        return Result.success(dishVOs);
    }

    /**
     * 检查菜品名称是否重复
     *
     * @param dish 被检查的菜品名称所属对象
     * @return 重复返回true，否则返回false
     */
    private boolean isNameDuplicate(Dish dish) {
        // 健壮性判断，不能为空
        if (StringUtils.isBlank(dish.getName())) {
            return true;
        }

        // 查询菜品名称是否已经存在
        return dishMapper.selectCountByName(dish) > 0;
    }
}
